﻿
namespace ZquenceStudio3Host.DspPlugins.Synthesizers.Nodesizer.Engine.Modules.HighLevel
{
    [ModuleDisplay("Resonance")]
    public class ResonantModule : BaseModule
    {
        private double fb;
        private double buf0 = 0.0;
        private double buf1 = 0.0;
        
        public readonly ModuleInput InputResonant;
        public readonly ModuleInput InputCutoff;

        public readonly ModuleInput Input;
        public readonly ModuleOutput Output;
        
        public ResonantModule(ModuleManager manager)
            : base(manager)
        {
            AddInput(InputResonant = new ModuleInput("Resonance", IOType.Audio, this));
            AddInput(InputCutoff = new ModuleInput("Cutoff", IOType.Audio, this));
            AddInput(Input = new ModuleInput("Input", IOType.Audio, this));
            AddOutput(Output = new ModuleOutput("Output", IOType.Audio, this));
        }
        
        public override void Process()
        {
            // If VolymeController is connected.
            if (Input.IsConnected && InputCutoff.IsConnected && InputResonant.IsConnected)
            {
                int length = Input.FromOutput.AudioBuffer.Length;
                double[] inputCutoff = InputCutoff.FromOutput.AudioBuffer.Buffer;
                double[] inputResonant = InputResonant.FromOutput.AudioBuffer.Buffer;
                double[] input = Input.FromOutput.AudioBuffer.Buffer;
                double[] output = Output.AudioBuffer.Buffer;
                for (int i = 0; i < length; i++)
                {
                    checked
                    {
                        double cutoff = inputCutoff[i];
                        double res = inputResonant[i];

                        Limit(ref cutoff, 0.01, 0.99);
                        Limit(ref res, 0.01, 0.99);

                        // Set feedback amount given f and q between 0 and 1.
                        fb = res + res / (1.0 - cutoff);
                        
                        buf0 = buf0 + cutoff * (input[i] - buf0 + fb * (buf0 - buf1));
                        buf1 = buf1 + cutoff * (buf0 - buf1);
                        output[i] = buf1;
                    }
                }
            }
        }
    }
}
